module;
#include <type_traits>
export module Code_19_8_3;

//[1]
template<typename... Elements>
class Typelist {};
//[1]
template<typename T>
struct IsFunctionT : std::false_type {}; //primary template: no function
//[1]
template<typename R, typename... Params>
struct IsFunctionT<R(Params...)> : std::true_type   //functions
{
    using Type = R;
    using ParamsT = Typelist<Params...>;
    static constexpr bool variadic = false;
};
//[1]
template<typename R, typename... Params>
struct IsFunctionT<R(Params..., ...)> : std::true_type     //variadic functions
{
    using Type = R;
    using ParamsT = Typelist<Params...>;
    static constexpr bool variadic = true;
};

//[2]
template<typename R, typename... Params>
struct IsFunctionT<R(Params...) const> : std::true_type
{
    using Type = R;
    using ParamsT = Typelist<Params...>;
    static constexpr bool variadic = false;
};
//[2]
template<typename R, typename... Params>
struct IsFunctionT<R(Params..., ...) volatile> : std::true_type 
{
    using Type = R;
    using ParamsT = Typelist<Params...>;
    static constexpr bool variadic = true;
};
//[2]
template<typename R, typename... Params>
struct IsFunctionT<R(Params..., ...) const volatile> : std::true_type 
{
    using Type = R;
    using ParamsT = Typelist<Params...>;
    static constexpr bool variadic = true;
};
//[2]
template<typename R, typename... Params>
struct IsFunctionT<R(Params..., ...)&> : std::true_type 
{
    using Type = R;
    using ParamsT = Typelist<Params...>;
    static constexpr bool variadic = true;
};
//[2]
template<typename R, typename... Params>
struct IsFunctionT<R(Params..., ...) const&> : std::true_type 
{
    using Type = R;
    using ParamsT = Typelist<Params...>;
    static constexpr bool variadic = true;
};

export
namespace Code_19_8_3 {

    void run()
    {

    }
}